﻿using PlateNumVideo.Entity;
using PlateNumVideo.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;


namespace PlateNumVideo.RealR3
{
    public class RealR3Video : IPlateNumVideo
    {
        /// <summary>
        /// 设备句柄
        /// </summary>
        public int DeviceHandle { get; set; }

        /// <summary>
        /// 播放句柄
        /// </summary>
        public int PlayHandle { get; set; }

        /// <summary>
        /// 设备初始化参数
        /// </summary>
        public InitPlateParam PlateParams { get; set; }

        /// <summary>
        /// 图片路径
        /// </summary>
        public string ImagePath { get; set; }

        /// <summary>
        /// 抓拍图片路径
        /// </summary>
        public string SnapImagePath { get; set; }

        /// <summary>
        /// 车号识别队列
        /// </summary>
        public Stack<PlateNumRes> PlateNums { get; set; }

        /// <summary>
        /// 是否初始化
        /// </summary>
        public bool IsInit { get; set; }

        /// <summary>
        /// 车号回调函数
        /// </summary>
        public Action<PlateNumRes> PlateNumCall { get; set; }

        /// <summary>
        /// 识别回调函数
        /// </summary>
        private VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK PlateResultCall = null;

        /// <summary>
        /// GPIO输入回调函数
        /// </summary>
        private VzClientSDK.VZLPRC_GPIO_RECV_CALLBACK GpioRecvCall = null;

        public RealR3Video() 
        {
            DeviceHandle = -1;
            PlayHandle = -1;
            IsInit = false;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="initPlateParam">初始化参数</param>
        public void Init(InitPlateParam initPlateParam)
        {
            PlateParams = initPlateParam;
            PlateNumCall = PlateParams?.CallFunc;
            ImagePath = Application.StartupPath + "/plateNum/Rec/";
            SnapImagePath = Application.StartupPath + "plateNum/SnapImage/";
            PlateNums = new Stack<PlateNumRes>();
            GpioRecvCall = new VzClientSDK.VZLPRC_GPIO_RECV_CALLBACK(OnGPIORecv);
            IsInit = true;
            VzClientSDK.VzLPRClient_Setup();
        }

        /// <summary>
        /// 打开设备
        /// </summary>
        /// <param name="openParam">设备参数</param>
        /// <returns></returns>
        public Tuple<bool, string> Open()
        {
            if(!IsInit)
            {
                return new Tuple<bool, string>(false, "请先初始化，再执行打开操作");
            }

            if(PlateParams == null || string.IsNullOrEmpty(PlateParams.Ip) ||
                string.IsNullOrEmpty(PlateParams.Account) || string.IsNullOrEmpty(PlateParams.Pwd)
                || PlateParams.Port <= 0)
            {
                return new Tuple<bool, string>(false,"参数错误");
            }

            DeviceHandle = VzClientSDK.VzLPRClient_Open(PlateParams.Ip, (ushort)PlateParams.Port, PlateParams.Account, PlateParams.Pwd);

            if (DeviceHandle == 0)
            {
                return new Tuple<bool, string>(false, "打开设备失败");
            }

            VzClientSDK.VzLPRClient_SetIsShowPlateRect(DeviceHandle, 0);
            return new Tuple<bool, string>(true,"打开成功");
        }

        /// <summary>
        /// 开始播放
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, string> StartRealPlay()
        {
            if (!IsInit)
            {
                return new Tuple<bool, string>(false, "请先初始化，再执行预览操作");
            }
            try
            {
                if (DeviceHandle == 0)
                {
                    return new Tuple<bool, string>(false, "设备打开失败，无法播放");
                }

                if (PlateParams.PictureHandle == null)
                {
                    return new Tuple<bool, string>(false, "显示控件没有设置，无法播放显示");
                }

                if (PlayHandle > 0)
                {
                    VzClientSDK.VzLPRClient_StopRealPlay(PlayHandle);
                    PlayHandle = 0;
                }

                PlayHandle = VzClientSDK.VzLPRClient_StartRealPlay(DeviceHandle, PlateParams.PictureHandle);

                // 设置车牌识别结果回调
                PlateResultCall = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                VzClientSDK.VzLPRClient_SetPlateInfoCallBack(DeviceHandle, PlateResultCall, IntPtr.Zero, 1);
                VzClientSDK.VzLPRClient_SetGPIORecvCallBack(DeviceHandle, GpioRecvCall, IntPtr.Zero);
                if (PlayHandle < 0)
                {
                    return new Tuple<bool, string>(false, "失败");
                }
                else
                {
                    return new Tuple<bool, string>(true, "成功");
                }
            }
            catch(Exception ex)
            {
                return new Tuple<bool, string>(false,ex.Message+ex.StackTrace);
            }
        }

        /// <summary>
        /// 抓拍图片
        /// </summary>
        /// <returns></returns>
        public Tuple<bool,string, string> SnapImage()
        {
            if (!IsInit)
            {
                return new Tuple<bool,string, string>(false,string.Empty, "请先初始化，再执行抓拍操作");
            }
            if (!Directory.Exists(SnapImagePath))
            {
                Directory.CreateDirectory(SnapImagePath);
            }
            string timeStr = string.Format("{0:yyyyMMddHHmmssffff}", DateTime.Now);
            string filePath = SnapImagePath + timeStr + ".jpg";
            if(PlayHandle >= 0)
            {
                var res = VzClientSDK.VzLPRClient_GetSnapShootToJpeg2(PlayHandle, filePath, 90);
                if (res == 0)
                {
                    return new Tuple<bool,string, string>(true, filePath, "成功");
                }
                else
                {
                    return new Tuple<bool,string, string>(false,string.Empty, "失败");
                }
            }
            else
            {
                return new Tuple<bool,string, string>(false, string.Empty, "设备预览失败，无法抓拍图片");
            }
        }

   

        /// <summary>
        /// 停止预览
        /// </summary>
        /// <param name="stopRealPlayParams"></param>
        /// <returns></returns>
        public Tuple<bool, string> StopRealPlay()
        {
            if (!IsInit)
            {
                return new Tuple<bool, string>(false, "请先初始化，再执行停止预览操作");
            }
            if (PlayHandle > 0)
            {
                int res = VzClientSDK.VzLPRClient_StopRealPlay(PlayHandle);
                if(res == 0)
                {
                    PlayHandle = 0;
                    VzClientSDK.VzLPRClient_SetPlateInfoCallBack(DeviceHandle, null, IntPtr.Zero, 0);
                    return new Tuple<bool, string>(true,"停止预览成功");
                }
                else
                {
                    return new Tuple<bool, string>(false, "停止预览失败");
                }
            }
            else
            {
                return new Tuple<bool, string>(true,"设备当前不处于预览状态，无需停止预览");
            }
        }

        /// <summary>
        /// 关闭
        /// </summary>
        /// <param name="closeParams"></param>
        /// <returns></returns>
        public Tuple<bool, string> Close()
        {
            if (DeviceHandle  == -1)
            {
                return new Tuple<bool, string>(true,"设备非打开状态，无需关闭");
            }
            else
            {
                if(PlayHandle > 0)
                {
                    StopRealPlay();
                }

                var res =VzClientSDK.VzLPRClient_Close(DeviceHandle);
                if(res == 0)
                {
                    return new Tuple<bool, string>(true,"关闭成功");
                }
                else
                {
                    return new Tuple<bool, string>(false, "关闭失败");
                }
            }
        }

        private int OnPlateResult(int handle, IntPtr pUserData,
                                          IntPtr pResult, uint uNumPlates,
                                          VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType,
                                          IntPtr pImgFull,
                                          IntPtr pImgPlateClip)
        {
            if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
            {
                VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
                string strLicense = new string(result.license);
                strLicense = strLicense.Trim('\0');
                if (!Directory.Exists(ImagePath))
                {
                    Directory.CreateDirectory(ImagePath);
                }

                DateTime now = DateTime.Now;
                string sTime = string.Format("{0:yyyyMMddHHmmssffff}", now);
                string path = ImagePath + sTime + ".jpg";
                VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 100);
                if (PlateNums.Count > 300) PlateNums.Clear();
                var plateItem = new PlateNumRes()
                {
                    PlateNum = strLicense,
                    ImagePath = path,
                    RecTime = DateTime.Now
                };
                PlateNums.Push(plateItem);
                if(PlateNumCall != null)
                {
                     PlateNumCall(plateItem);
                }
            }

            return 0;
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="nGPIOId"></param>
        /// <param name="nVal"></param>
        /// <param name="pUserData"></param>
        private void OnGPIORecv(int handle, int nGPIOId, int nVal, IntPtr pUserData)
        {
        }

        public PlateNumRes GetPlateNum()
        {
            if(PlateNums.Count > 0)
            {
                var res =  PlateNums.Pop();
                PlateNums.Clear();
                return res;
            }
            else
            {
                return null;
            }
        }
    }
}
